#include<t_stdio.h>
#include<t_file.h>
#include <sys/types.h>      
#include <sys/socket.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <sys/select.h>
#include<stdlib.h>
#include <arpa/inet.h>
#include<signal.h>
#include<net/if.h>
#include <sys/ioctl.h>
#define DBGPRINT printf

void sig_process(int signo){//信号处理函数
    printf("catch a exit signal..\n");
    _exit(0);
}


int main(int argc ,char * argv[]){
    int ret = -1 , sock = -1 , so_broadcast = 1, from_len = 0, count = 0;
    struct ifreq ifr;
    struct sockaddr_in broadcast_addr ; //本地广播地址
    struct sockaddr_in server_addr ; //服务器地址

    fd_set readfd ; //设置接收信息合集，和服务器代码一样
    char buffer[32];//设置数据数组，用于数据接收发送
    struct timeval timeout ;//超时设置
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;

    signal(SIGINT,sig_process);//添加sigint信号到信号掩码

    sock = socket(AF_INET , SOCK_DGRAM , 0); //创建UDP数据报套接字
    if(sock < 0 ) E_MSG("socket" , -1);

    //将需要使用的网络接口字符串复制到网卡结构中
    strcpy(ifr.ifr_name , "ens33");

    //获取广播地址
    if(ioctl(sock,SIOCGIFBRDADDR, &ifr ) == -1){
        E_MSG("ioctl",-1);
    }

    //将获得的广播地址给本地广播地址结构
    memcpy(&broadcast_addr , &ifr.ifr_broadaddr , sizeof(struct sockaddr_in));

    //设置广播端口
    broadcast_addr.sin_port = htons(8888) ; //设置广播端口

    //设置套接字可以进行广播操作
    ret = setsockopt(sock , SOL_SOCKET , SO_BROADCAST , &so_broadcast ,sizeof(so_broadcast));

    //开始发送广播信息
    int times = 10 , i = 0 ;
    for(i = 0 ; i < times ; i++){
        //广播发送服务器地址请求
        ret = sendto(sock , "IP_FOUND" , strlen("IP_FOUND") , 0 ,(struct sockaddr * ) &broadcast_addr , sizeof(broadcast_addr));
        if(ret == -1)continue ; //发送失败就继续下一次发送
         //先将文件描述符清零
        FD_ZERO(&readfd);
        //将套接字文件描述符加入读集合
        FD_SET(sock,&readfd);
        //监听是否有数据到来
         ret = select(sock+1 , &readfd , NULL,NULL,&timeout); //这里和服务器代码一样

        switch (ret)
        {
        case -1:
            //发生错误
            break;
        case 0 :
            //超时
            break;
        default://成功监听到服务器回应
             if(FD_ISSET(sock , &readfd)){
                count = recvfrom(sock , buffer , 32 , 0 ,(struct sockaddr *)&server_addr , &from_len );
                DBGPRINT("recv msg is %s\n" , buffer);
                //判断是否为广播回应消息
                 if(strstr(buffer , "IP_FOUND_ACK")){
                    printf("found server IP is %s\n", inet_ntoa(server_addr.sin_addr));//打印服务器ip地址
                 }
                 break;

             }
        }
    }
    return 0;
}